import requests
from lxml import etree
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
from functools import lru_cache

# 原始函数保持不变，但做一些小优化
def fetch_match_data(mid, cid):
    start_time = time.time()
    
    url = f'http://vip.titan007.com/changeDetail/3in1Odds.aspx?id={mid}&companyid={cid}&l=0'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.97 Safari/537.36 Core/1.116.562.400 QQBrowser/19.6.6725.400',
        'Referer': 'http://vip.titan007.com/'
    }
    
    try:
        response = requests.get(url, headers=headers, timeout=10)
        if response.status_code != 200:
            print(f"请求失败，状态码：{response.status_code}")
            return None
    except Exception as e:
        print(f"请求异常: {e}")
        return None

    html_tree = etree.HTML(response.text)
    
    # 快速检查是否有数据
    all_tr_elements = html_tree.xpath('//div[1]/table//tr[2]')
    print(all_tr_elements)
    if len(all_tr_elements) == 0:
        print(f'{mid} 比赛没有三合一数据！')
        return None
    
    # 进球时间处理
    red_rows = html_tree.xpath('//div[1]/table//tr[td[@style="background-color:red;color:White;"]]')
    red_items = []
    for row in red_rows:
        jinqiu_time_temp = row.xpath('td[1]/text()')
        score = row.xpath('td[2]/text()')
        if jinqiu_time_temp and score:
            jinqiu_time = '45' if jinqiu_time_temp[0] == '中场' else jinqiu_time_temp[0]
            red_items.append({"jinqiu_time": jinqiu_time, "score": score[0].strip()})
    
    red_items.reverse()
    
    def parse_score(s):
        try:
            home, away = map(int, s.split("-"))
            return home, away
        except:
            return (0, 0)

    invalid_indices = set()
    for i in range(len(red_items)):
        if i in invalid_indices:
            continue
        
        curr_home, curr_away = parse_score(red_items[i]["score"])
        curr_total = curr_home + curr_away
        
        for j in range(i + 1, len(red_items)):
            next_home, next_away = parse_score(red_items[j]["score"])
            next_total = next_home + next_away
            
            if next_total < curr_total:
                invalid_indices.add(i)
                invalid_indices.add(j)
                break

    valid_times = [
        item["jinqiu_time"] 
        for idx, item in enumerate(red_items) 
        if idx not in invalid_indices 
        and sum(parse_score(item["score"])) > 0
    ]
    
    goal_time = "'/".join(valid_times) + "'" if valid_times else ""

    # 终盘数据
    closing_session_text = html_tree.xpath('//div[1]/table//tr[td[@class="hg_red"]][1]/td[position()>=3 and position()<=5]//text()')
    closing_session_text = " ".join(closing_session_text)

    # 中场让球盘
    midfield = ""
    midfield_elements = html_tree.xpath('//div[1]/table//tr[td[1][text()="中场"]]')
    if midfield_elements:
        for element in midfield_elements:
            texts = element.xpath('./td[position()>=3 and position()<=5]//text()')
            if texts and '封' not in texts:
                midfield = " ".join(texts)
                break
    else:
        first_half_elements = html_tree.xpath('//div[1]/table//tr[td[1][number(text())<=45]]')
        for element in first_half_elements:
            texts = element.xpath('./td[position()>=3 and position()<=5]//text()')
            if texts and '封' not in texts:
                midfield = " ".join(texts)
                break
        else:
            first_half_element = html_tree.xpath('//div[1]/table//tr[td[1][number(text())<=45]][1]/td[position()>=3 and position()<=5]//text()')
            midfield = " ".join(first_half_element)

    # 大小盘数据
    big_small_texts = html_tree.xpath('//div[2]/table//tr[td[@class="hg_red"]][1]/td[4]//text()')
    big_small_texts = " ".join(big_small_texts)

    # 中场大小盘
    mid_big_small_texts = ""
    mid_big_small_elements = html_tree.xpath('//div[2]/table//tr[td[1][text()="中场"]]')
    if mid_big_small_elements:
        for element in mid_big_small_elements:
            texts = element.xpath('./td[4]//text()')
            if texts and '封' not in texts:
                mid_big_small_texts = " ".join(texts)
                break
    else:
        first_half_elements = html_tree.xpath('//div[2]/table//tr[td[1][number(text())<=45]]')
        for element in first_half_elements:
            texts = element.xpath('./td[4]//text()')
            if texts and '封' not in texts:
                mid_big_small_texts = " ".join(texts)
                break
        else:
            first_half_element = html_tree.xpath('//div[2]/table//tr[td[1][number(text())<=45]][1]/td[4]//text()')
            mid_big_small_texts = " ".join(first_half_element)

    # 表格HTML内容
    tables = {}
    for div_index in [1, 2, 3]:
        table_elements = html_tree.xpath(f'//div[{div_index}]/table')
        if table_elements:
            table_html = etree.tostring(table_elements[0], encoding='unicode', pretty_print=False)
            tables[f'table_{div_index}'] = table_html.replace('&#13;', '').replace('\r', '')
        else:
            tables[f'table_{div_index}'] = ""

    end_time = time.time()
    execution_time = end_time - start_time
    print(f"比赛 {mid} 处理时间: {execution_time:.2f} 秒")

    return [
        goal_time,
        closing_session_text,
        midfield,
        big_small_texts,
        mid_big_small_texts,
        tables.get('table_1', ''),
        tables.get('table_2', ''),
        tables.get('table_3', '')
    ]

# 优化后的并发处理版本
def fetch_match_data_concurrent(matches, max_workers=10):
    """
    并发处理多个比赛数据
    matches: [(mid, cid), ...] 列表
    max_workers: 最大并发线程数
    """
    results = {}
    
    # 分批处理，每批最多6个比赛
    batch_size = 6
    batches = [matches[i:i + batch_size] for i in range(0, len(matches), batch_size)]
    
    total_batches = len(batches)
    print(f"总共 {len(matches)} 个比赛，分 {total_batches} 批处理，每批最多 {batch_size} 个比赛")
    
    for batch_index, batch in enumerate(batches):
        print(f"正在处理第 {batch_index + 1}/{total_batches} 批...")
        batch_start_time = time.time()
        
        with ThreadPoolExecutor(max_workers=min(max_workers, len(batch))) as executor:
            # 提交所有任务
            future_to_match = {
                executor.submit(fetch_match_data, mid, cid): (mid, cid) 
                for mid, cid in batch
            }
            
            # 获取结果
            for future in as_completed(future_to_match):
                match = future_to_match[future]
                try:
                # 增加超时时间
                    result = future.result(timeout=30)
                    results[match] = result
                except Exception as e:
                    print(f"处理比赛 {match} 时出错: {e}")
                    results[match] = None
        
        batch_end_time = time.time()
        print(f"第 {batch_index + 1} 批处理完成，耗时: {batch_end_time - batch_start_time:.2f} 秒")
    
    return results

def convert_tuple_keys_to_str(data):
    """
    将字典中tuple类型的key转换为字符串格式，以便JSON序列化
    """
    if isinstance(data, dict):
        new_dict = {}
        for key, value in data.items():
            # 如果键是元组，则转换为字符串
            if isinstance(key, tuple):
                new_key = f"{key[0]}_{key[1]}"  # 格式: "mid_cid"
            else:
                new_key = key
                
            # 递归处理值
            if isinstance(value, dict):
                new_dict[new_key] = convert_tuple_keys_to_str(value)
            elif isinstance(value, list):
                new_dict[new_key] = [convert_tuple_keys_to_str(item) if isinstance(item, dict) else item for item in value]
            else:
                new_dict[new_key] = value
        return new_dict
    return data

# 使用示例
if __name__ == '__main__':
    # 示例数据
    matches = [
        (2419549, 3),
        # (2001786, 3),
        # (2539327, 3),
        # (2617485, 3),
        # (2734730, 3),
        # (2701135, 3),
        # (2429040, 3),
        # (2438215, 3),
        # (2490464, 3),
        # (2352463, 3),
        
        # 添加更多比赛...
    ]
    
    # 方法1: 多线程并发处理
    start_time = time.time()
    results = fetch_match_data_concurrent(matches, max_workers=20)
    end_time = time.time()
    print(f"多线程处理 {len(matches)} 个比赛耗时: {end_time - start_time:.2f} 秒")
    # 写入json文件
    import json
    with open('output.json', 'w', encoding='utf-8') as f:
        json.dump(convert_tuple_keys_to_str(results), f, ensure_ascii=False, indent=4)